home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / KeyPressManagerPanel.java < prev    next >
Text File  |  1998-08-21  |  13KB  |  407 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.*;
  4. import java.awt.event.*;
  5. import java.util.Vector;
  6. import java.beans.PropertyVetoException;
  7. import java.beans.PropertyChangeListener;
  8. import java.beans.VetoableChangeListener;
  9. import java.beans.PropertyChangeEvent;
  10.  
  11. //     03/03/97    RKM    Fixed a bug in doTab, where it would tab to a hidden component
  12. //     03/13/97    RKM    Added code in HandleEvent to handle return being hit in TextFields which
  13. //                    results in a Action being sent
  14. //     03/13/97    RKM    Added ability to tab to TextComponents only, and defaulted it true for Mac
  15. //                    On platforms that support tabbing this is not needed, but on the Mac tabbing
  16. //                    would stop if you hit anything but a TextComponent - this seems a descent solution
  17. //
  18. //                    When encountering a non TextComponent on the Mac before defaulting to true:
  19. //                        Netscape - would not tab to the next component
  20. //                        Symantec - focus would be lost
  21. //                        Apple - tabbing works, but no focus is shown in non TextComponents and keys do nothing (ie List)
  22. //                        MW - same as Apple
  23. //  05/15/97    CAR Changed doTab to "deselect" the text of the text component being tabbed from
  24. //    06/01/97    RKM    Updated to support Java 1.1
  25. //                    Made properties bound & constrained
  26. //                    Updated mechanism to keep track of contents of panel
  27. //                    Removed FKey to event binding mechanism (could I even support it?)
  28. //                    Removed tabbing functionality, since JDK 1.1 fixes this
  29. //    06/01/97    LAB    Removed non-functioning deprecated methods.  Changed vetos and changes to private
  30. //                    from protected. Updated the version to 1.1.
  31. //  07/29/97    CAR inner adaptor class implements java.io.Serializable
  32. //  08/13/97    RKM Removed tabbed - it did nothing
  33. //                    Removed setTabStop - it did nothing (with tabber removed)
  34. //                    Removed tabToTextComponentsOnly
  35. //                    Removed AutoTabState property
  36. //                    Removed all bound and constrained property stuff (it was no longer needed)
  37. //  08/19/97    CAR constructor now calls super.setLayout(null)
  38. //  08/19/97    BS  don't add keylistener when the component added is a grid=>grid now functional
  39. //                  setCancelButton() and setDefaultButton() did not work, fixed message dispatching
  40. //  08/28/97    CAR corrected typo in componentRemoved()
  41. //  08/28/97    CAR when TAB is hit on last traversable item in panel focus goes back to first
  42. //                  traversable item in panel.  CTRL+TAB transfers focus to next traversable item
  43. //                  outside of the panel.
  44.  
  45. //
  46. //
  47.  
  48. //???RKM??? I could not figure out an easy way to implement the tab hack that was previously here,
  49. //            What it did was this, on lose focus it would save the event, if a key was pressed it would
  50. //            remove the event, but if a key release was done (if it still had the event), it would
  51. //            treat act as if a key had been pressed
  52.  
  53. /**
  54.  * A Panel extension which provides for
  55.  * tabbing between components and supporting certain key accelerations
  56.  * by posting events provided by the user. Can be used directly or extended.
  57.  * When extending be sure to super()
  58.  * during construction and to super.handleEvent(evt) from
  59.  * handleEvent if you override it.
  60.  * <p>
  61.  * The tab focus order is based on the order in which the components were
  62.  * added to the panel. Each component receives
  63.  * focus in turn, but the mouse cursor is not relocated. Look at the Project
  64.  * window to see the tab order of components within the KeyPressManagerPanel.
  65.  * You can change the tab order by moving the component names in the Project
  66.  * window list, or by adding them to the panel in a different order in your
  67.  * source code.
  68.  * <p>
  69.  * Components respond to default events when they receive focus. For example,
  70.  * the TextField component displays text input from the keyboard, and the
  71.  * Button component issues an action event when it is clicked.
  72.  * <p>
  73.  * Use KeyPressManagerPanel to create a panel whose elements can be tabbed
  74.  * through, and specifically to:
  75.  * <UL>
  76.  * <DT>╖ Create a subcontainer that organizes container space within an Applet,
  77.  * Frame or Dialog container. This simplifies your component layout task.</DT>
  78.  * <DT>╖ Hold other specialized Panel containers.</DT>
  79.  * </UL>
  80.  * @version 1.1, July 18, 1997
  81.  * @author Symantec
  82.  */
  83. public class KeyPressManagerPanel extends Panel implements java.io.Serializable
  84. {
  85.     /**
  86.      * Constructs a Panel which handles key press events.
  87.      * By default, components added to this panel can be tabbed to. To change
  88.      * this call method setAutoTabState() with false before adding components
  89.      * that can't be tabbed to.
  90.      */
  91.     public KeyPressManagerPanel()
  92.     {
  93.         super.setLayout(null);
  94.         resetKeyManager();
  95.     }
  96.  
  97.     /**
  98.      * Resets all KeyPressManager associations (default button, cancel
  99.      * button, tab stop list).
  100.      */
  101.     public void resetKeyManager()
  102.     {
  103.         removeDefaultButton();
  104.         removeCancelButton();
  105.     }
  106.  
  107.     /**
  108.      * Sets the button to press when the Enter or Return key
  109.      * is pressed.
  110.      * @param button the button to set as default
  111.      * @see #removeDefaultButton
  112.      */
  113.     public void setDefaultButton(Button button)
  114.     {
  115.         removeDefaultButton();
  116.         defaultButton = button;
  117.     }
  118.  
  119.     /**
  120.      * Removes Enter/Return key association with current default
  121.      * button/event.
  122.      * @see #setDefaultButton
  123.      */
  124.     public void removeDefaultButton()
  125.     {
  126.         defaultButton = null;
  127.     }
  128.  
  129.     /**
  130.      * @deprecated defaultButton will be sent action and focus will be set
  131.      * @see #setDefaultButton(java.awt.Button)
  132.      */
  133.     public void setDefaultButton(Button button, Event evt, Container deliverTo, boolean bSetFocus)
  134.     {
  135.         setDefaultButton(button);
  136.     }
  137.  
  138.     /**
  139.      * Sets the button to press when the Escape key is pressed.
  140.      * @param button the button to set as Cancel
  141.      * @see #removeCancelButton
  142.      */
  143.     public void setCancelButton(Button button)
  144.     {
  145.         removeCancelButton();
  146.         cancelButton = button;
  147.     }
  148.  
  149.     /**
  150.      * Removes Escape key association with current Cancel button/event.
  151.      * @see #setCancelButton
  152.      */
  153.     public void removeCancelButton()
  154.     {
  155.         cancelButton = null;
  156.     }
  157.  
  158.     /**
  159.      * @deprecated CancelButton will be sent action and focus will be set.
  160.      * @see #setCancelButton(java.awt.Button)
  161.      */
  162.     public void setCancelButton(Button button, Event evt, Container deliverTo, boolean bSetFocus)
  163.     {
  164.         setCancelButton(cancelButton);
  165.     }
  166.  
  167.     //
  168.     // Implementation
  169.     //
  170.  
  171.     //???RKM??? As soon as we get to zips, fix this
  172.     class A/*ction*/ implements ActionListener, java.io.Serializable
  173.     {
  174.         public void actionPerformed(ActionEvent evt)
  175.         {
  176.             sendAction(defaultButton);
  177.         }
  178.     }
  179.  
  180.     //???RKM??? As soon as we get to zips, fix this
  181.     class K/*ey*/ extends KeyAdapter implements java.io.Serializable
  182.     {
  183.         //???RKM??? Switch to keyTyped when this works
  184.         public void keyPressed(KeyEvent evt)
  185.         //public void keyTyped(KeyEvent evt)
  186.         {
  187.             if (consumeKeyTyped(evt))
  188.                 evt.consume();
  189.         }
  190.     }
  191.  
  192.     /**
  193.      * Inserts a component into this container at the given position, and
  194.      * adds it to the layout manager using the specified constraints object.
  195.      * <p>
  196.      * This is a standard Java AWT method which is overridden to track
  197.      * every add request to a container.
  198.      *
  199.      * @param component the component to add
  200.      * @param constraints the positioning constraints for the layout manager
  201.      * @param index the zero-relative index at which to add the component,
  202.      * or -1 to append to the end
  203.      * @see #remove
  204.      */
  205.     protected void addImpl(Component component, Object constraints, int index)
  206.     {
  207.         componentAdded(component);
  208.  
  209.         super.addImpl(component,constraints,index);
  210.     }
  211.  
  212.     /**
  213.      * Removes the component at the specified zero-relative index from this
  214.      * container.
  215.      * <p>
  216.      * This is a standard Java AWT method which gets called to remove a
  217.      * component from a container. When this happens the component's
  218.      * removeNotify() will also get called to indicate component removal.
  219.      *
  220.      * @param index the zero-relative index of the component to remove
  221.      * @see #removeAll
  222.      * @see java.awt.Container#add
  223.      */
  224.     public void remove(int index)
  225.     {
  226.         componentRemoved(getComponent(index));
  227.  
  228.         super.remove(index);
  229.     }
  230.  
  231.     /**
  232.      * Removes all the components from this container.
  233.      * <p>
  234.      * This is a standard Java AWT method which gets called to remove all
  235.      * the components from a container. When this happens each component's
  236.      * removeNotify() will also get called to indicate component removal.
  237.      *
  238.      * @see #remove
  239.      * @see java.awt.Container#add
  240.      */
  241.     public void removeAll()
  242.     {
  243.         //Make certain we remove them from our internal records
  244.         Component[] components = getComponents();
  245.         for (int i = 0;i < components.length;i++)
  246.             componentRemoved(components[i]);
  247.  
  248.         super.removeAll();
  249.     }
  250.  
  251.     /**
  252.      * This helper method sends an action event to the specified button.
  253.      */
  254.     protected boolean sendAction(Button button)
  255.     {
  256.         if (button != null)
  257.         {
  258.             if (button.isEnabled())
  259.             {
  260.                 //???RKM??? Should we check if it is visible
  261.                 button.requestFocus();
  262.  
  263.                 //Send an acion event to the component
  264.                 button.dispatchEvent(new ActionEvent(button,ActionEvent.ACTION_PERFORMED,new String(button.getLabel())));
  265.  
  266.                 return true;
  267.             }
  268.         }
  269.  
  270.         return false;
  271.     }
  272.  
  273.     /**
  274.      * Internally called utility routine that handles ENTER and ESCAPE key processing.
  275.      * @param evt the key event
  276.      * @return true if an action event was sent to the default button
  277.      */
  278.     protected boolean consumeKeyTyped(KeyEvent evt)
  279.     {
  280.         switch (evt.getKeyCode())
  281.         {
  282.             case KeyEvent.VK_ENTER:
  283.             {
  284.                 return sendAction(defaultButton);
  285.             }
  286.  
  287.             case KeyEvent.VK_ESCAPE:
  288.             {
  289.                 return sendAction(cancelButton);
  290.             }
  291.  
  292.             case KeyEvent.VK_TAB:
  293.             {
  294.                 return handleTabEvent(evt);
  295.             }
  296.         }//switch
  297.  
  298.         return false;
  299.     }
  300.  
  301.     /**
  302.      * Internally called utility routine that handles TAB key processing.
  303.      * @param evt the key event
  304.      * @return true if an event was processed
  305.      */
  306.     protected boolean handleTabEvent(KeyEvent evt)
  307.     {
  308.         Component[] ca = getComponents();
  309.         Component lastTraversable = null;
  310.         int i = ca.length - 1;
  311.  
  312.         do {
  313.             if (ca[i].isFocusTraversable() == true)
  314.                 lastTraversable = ca[i];
  315.             else
  316.                 --i;
  317.         } while(ca[i].isFocusTraversable() != true && i >= 0);
  318.  
  319.         if (lastTraversable == null)
  320.             return false;
  321.  
  322.         if((evt.getModifiers() & java.awt.event.InputEvent.CTRL_MASK)
  323.             == java.awt.event.InputEvent.CTRL_MASK) {
  324.                 lastTraversable.transferFocus();
  325.                 return true;
  326.         }
  327.  
  328.         if(evt.getComponent() == lastTraversable)
  329.         {
  330.             for(i = 0; i < ca.length; ++i) {
  331.                 if(ca[i].isFocusTraversable() == true) {
  332.                     ca[i].requestFocus();
  333.                     return true;
  334.                 }
  335.             }
  336.         }
  337.  
  338.         return false;
  339.     }
  340.  
  341.     /**
  342.      * Sets the tab stop if necessary, hooks up any listeners we need.
  343.      * Called when any component is added to the panel
  344.      * @param component component being added to the panel.
  345.      * @see #componentRemoved
  346.      */
  347.     protected void componentAdded(Component component)
  348.     {
  349.         //If the component is already in the panel, don't process it
  350.         if (symantec.itools.awt.util.Util.findComponent(this,component) != -1)
  351.             return;
  352.  
  353.         if(component instanceof java.awt.TextField)
  354.         {
  355.             java.awt.TextField textField = (java.awt.TextField)component;
  356.             textField.addActionListener(action);
  357.         }
  358.  
  359.         if(!component.getClass().getName().equals("symantec.itools.db.awt.Grid"))
  360.                 component.addKeyListener(key);
  361.  
  362.     }
  363.  
  364.     /**
  365.      * Utility routined automatically called before a component is removed from this panel.
  366.      * It removes this panel's key event listeners and, for TextFields,
  367.      * action event listeners.
  368.      * @param component the component about to be removed from this panel
  369.      */
  370.     protected void componentRemoved(Component component)
  371.     {
  372.         //If the component is not in the panel, don't process it
  373.         if (symantec.itools.awt.util.Util.findComponent(this,component) == -1)
  374.             return;
  375.  
  376.         if(component instanceof java.awt.TextField)
  377.         {
  378.             java.awt.TextField textField = (java.awt.TextField)component;
  379.             textField.removeActionListener(action);
  380.         }
  381.  
  382.         if(!component.getClass().getName().equals("symantec.itools.db.awt.Grid"))
  383.                 component.removeKeyListener(key);
  384.     }
  385.  
  386.     //Protected members
  387.     /**
  388.      * The button to press when the Enter/Return key is pressed.
  389.      * @see #setDefaultButton
  390.      */
  391.     protected Button                    defaultButton;
  392.     /**
  393.      * The button to press when the Escape key is pressed.
  394.      * @see #setCancelButton
  395.      */
  396.     protected Button                    cancelButton;
  397.     /**
  398.      * Listens for an action and posts a default button action when triggered.
  399.      */
  400.     protected A                        action = new A();
  401.     /**
  402.      * Listens for an key and if appropriate posts a default or cancel button action.
  403.      */
  404.     protected K                        key = new K();
  405. }
  406.  
  407.